package etxt2db.minorthird;
import java.util.Iterator;
import java.util.List;

import edu.cmu.minorthird.classify.ExampleSchema;
import edu.cmu.minorthird.text.MonotonicTextLabels;
import edu.cmu.minorthird.text.NestedTextLabels;
import edu.cmu.minorthird.text.Span;
import edu.cmu.minorthird.text.TextLabels;


public class MultiClassAnnotationExample {
	public static String OUTSIDE = "outside";
	public static String INSIDE = "inside";
	public static String START = "start";
	public static String END = "end";
	public static String NOT_START_OR_END = "notStartOrEnd";
	private List<String> inputSpanTypes;

	private Span document;
	private TextLabels labels;

	/** 
	 * @param document give feedback to learner about this document
	 * @param labels feedback information is in these labels
	 * @param inputSpanType learner will learn how to extract spans of this type
	 */
	public MultiClassAnnotationExample(Span document,TextLabels labels,List<String> inputSpanTypes)
	{
		this.document = document;
		this.labels = labels;
		this.inputSpanTypes = inputSpanTypes;
	}

	public Span getDocumentSpan()
	{ return document; }

	public TextLabels getLabels()
	{ return labels; }

	public List<String> getInputTypes()
	{ return inputSpanTypes; }

	public String toString() {
		return "[AnnEx: document="+document+"]";
	}

	/** Return the name of the class associated with this span.  If
	 * inputSpanType is defined, the class name will be POS or NEG;
	 * otherwise, if inputSpanProp is defined, the class name will be
	 * the property value assigned, or NEG.
	 */
	public String getClassName(Span span)
	{
		String className = ExampleSchema.NEG_CLASS_NAME;
		if (getInputTypes()!=null) {
			for(String inputType : getInputTypes()){
				if (getLabels().hasType(span,inputType)) {
					className = inputType;
					break;
				}
			}
		} else {
			throw new IllegalStateException("inputType && inputProp undefined for answeredQuery: "+this);
		}
		return className;
	}

	//
	// convenience methods
	//
	public TextLabels labelTokensInsideOutside(String prop)
	{
		MonotonicTextLabels result = new NestedTextLabels(labels);
		String documentId = document.getDocumentId();
		for(String inputType : getInputTypes()){
			labelTokens(result,result.closureIterator(inputType,documentId),prop,OUTSIDE);
			labelTokens(result,result.instanceIterator(inputType,documentId),prop,INSIDE);
		}
		return result;
	}

	public TextLabels labelTokensStartEnd(String prop)
	{
		MonotonicTextLabels result = new NestedTextLabels(labels);
		String documentId = document.getDocumentId();
		for(String inputType : getInputTypes()){
			labelTokens(result,result.closureIterator(inputType,documentId),prop,NOT_START_OR_END);
			for (Iterator<Span> i=result.instanceIterator(inputType,documentId); i.hasNext(); ) {
				Span s = i.next();
				if (s.size()>0) {
					result.setProperty( s.getToken(0), prop, START );
					result.setProperty( s.getToken(s.size()-1), prop, END );
				}
			}
		}
		return result;
	}

	private void labelTokens(MonotonicTextLabels labels,Iterator<Span> i,String prop,String value)
	{
		while (i.hasNext()) {
			Span s = i.next();
			for (int j=0; j<s.size(); j++) {
				labels.setProperty( s.getToken(j), prop, value);
			}
		}
	}
}
